package jp.co.nes.awssupport.business.logic;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.List;

import jp.co.nes.awssupport.business.utility.TargetAmountHelper;
import jp.co.nes.awssupport.common.base.CommonException;
import jp.co.nes.awssupport.common.bean.ContractInformationBean;
import jp.co.nes.awssupport.common.bean.MiscellaneousExpensesAssignedBean;
import jp.co.nes.awssupport.common.bean.MiscellaneousExpensesGroupBean;
import jp.co.nes.awssupport.common.bean.MiscellaneousExpensesPlanBean;
import jp.co.nes.awssupport.common.bean.MonthlyCompiledBillingBean;
import jp.co.nes.awssupport.common.utility.DateUtil;

/**
 * 雑費プラン処理です。
 */
public class MiscellaneousExpensesPlanProcessing {

    /** 処理対象年月 */
    private YearMonth targetYearMonth;

    /** 契約情報管理 */
    private ContractInformationManage ciManage;

    /**
     * 処理対象年月を引数にもつコンストラクタです。
     *
     * @param targetYearMonth 処理対象年月
     */
    public MiscellaneousExpensesPlanProcessing(YearMonth targetYearMonth) {
        this.targetYearMonth = targetYearMonth;
        ciManage = new ContractInformationManage(targetYearMonth);
    }

    /**
     * 雑費グループに含まれる雑費プランを適用し、雑費適用リストを返却します。<br>
     * なお、雑費適用額は「係数 * 請求額(税抜) + 定数」で算出した結果を、小数第1位で四捨五入した値になります。<br>
     * 以下の場合、空リスト返却します。
     * <ul>
     * <li>雑費グループがnullの場合</li>
     * <li>雑費グループに設定されている雑費プランリストがnull or 空リストの場合</li>
     * </ul>
     * 【補足事項】
     * <ul>
     * <li>
     * 月次集計結果に含まれる請求額（税抜）は、小数第4位で四捨五入して小数第3位にした値の合計を、<br>
     * 小数第1位で四捨五入して整数にした値である必要があります。
     * </li>
     * </ul>
     *
     * @param mcbBean 月次集計結果
     * @return 雑費適用リスト
     */
    public List<MiscellaneousExpensesAssignedBean> apply(MonthlyCompiledBillingBean mcbBean) {
        String linkedAccountId = mcbBean.getLinkedAccountId();
        ContractInformationBean ciBean = ciManage.get(linkedAccountId);
        if (ciBean == null) {
            throw new CommonException("contract information not exist(linkedAccountId=" + linkedAccountId + ")");
        }

        List<MiscellaneousExpensesAssignedBean> applyList = new ArrayList<>();
        MiscellaneousExpensesGroupBean groupBean = ciBean.getMiscellaneousExpensesGroupBean();

        if (groupBean == null) {
            return applyList;
        }

        List<MiscellaneousExpensesPlanBean> planList = groupBean.getMiscellaneousExpensesPlanList();
        if (planList == null || planList.isEmpty()) {
            return applyList;
        }

        long billingAmount = mcbBean.getBillingAmount().longValueExact();
        TargetAmountHelper helper = new TargetAmountHelper(linkedAccountId, targetYearMonth);
        long targetAmount = helper.getTargetAmountOfMeAndPs(billingAmount);

        for (MiscellaneousExpensesPlanBean planBean : planList) {
            // 雑費適用額 = 係数 * 適用対象額 + 定数 (小数点第1位で四捨五入)
            BigDecimal coefficient = planBean.getCoefficient();
            BigDecimal constant = planBean.getConstant();
            BigDecimal multiplyValue = coefficient.multiply(new BigDecimal(targetAmount));
            BigDecimal miscellaneousExpensesAmount = multiplyValue.add(constant).setScale(0, RoundingMode.HALF_UP);

            MiscellaneousExpensesAssignedBean applyBean = new MiscellaneousExpensesAssignedBean();
            applyBean.setLinkedAccountId(linkedAccountId);
            applyBean.setYearMonth(DateUtil.toInt(targetYearMonth));
            applyBean.setAssignedPlanId(planBean.getPlanId());
            applyBean.setAssignedGroupId(groupBean.getGroupId());
            applyBean.setAssignedMiscellaneousExpensesName(planBean.getPlanName());
            applyBean.setTargetAmount(targetAmount);
            applyBean.setMiscellaneousExpensesAmount(miscellaneousExpensesAmount.longValueExact());
            applyList.add(applyBean);
        }
        return applyList;
    }
}
